package com.iwayin.web.common.utils;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;

import com.iwayin.core.utils.StringUtil;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 图片处理工具类
 * 
 * @author xiaobo.feng<xiaobo.feng@foxmail.com>
 * 
 *         Mar 8, 2012
 */
public class ImageUtil {

	public static final MediaTracker tracker = new MediaTracker(
			new Component() {

				private static final long serialVersionUID = -4205954905316314436L;

			});
	/**
	 * 
	 * @param src
	 * @param target
	 * @param width
	 * @param height
	 */
	public static void dengbiCompress(File src,File target,float width,float height){
		try {
			BufferedImage image = ImageIO.read(src);

			// 获得缩放的比例
			double ratio = 1.0;
			// 判断如果高、宽都不大于设定值，则不处理
			if (image.getHeight() > height || image.getWidth() > width) {
				if (image.getHeight() > image.getWidth()) {
					ratio = height / image.getHeight();
				} else {
					ratio = width / image.getWidth();
				}
			}
			// 计算新的图面宽度和高度
			int newWidth = (int) (image.getWidth() * ratio);
			int newHeight = (int) (image.getHeight() * ratio);

			BufferedImage bfImage = new BufferedImage(newWidth, newHeight,
					BufferedImage.TYPE_INT_RGB);
			bfImage.getGraphics().drawImage(
					image.getScaledInstance(newWidth, newHeight,
							Image.SCALE_SMOOTH), 0, 0, null);

			FileOutputStream os = new FileOutputStream(target);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
			encoder.encode(bfImage);
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 等比压缩图片
	 * 
	 * @param src
	 * @param target
	 * @param width
	 * @param height
	 */
	public static void dengbiCompress(String src, String target, float width,
			float height) {

		File srcfile = new File(src);
		if (!srcfile.exists()) {
			System.out.println("文件不存在");
			return;
		}
		dengbiCompress(srcfile, new File(target), width, height);

	}
	/**
	 * 
	 * @param src 源文件
	 * @param target 目标存储路径
	 * @param x //剪切点坐标
	 * @param y
	 * @param width//剪切宽
	 * @param height
	 */
	public static void cutImage(File src, String target, int x, int y,
			int width, int height) {
		FileInputStream fis = null;
		ImageInputStream iis = null;

		try {
			fis = new FileInputStream(src);

			Iterator<ImageReader> it = ImageIO
					.getImageReadersByFormatName("jpg");
			ImageReader reader = it.next();

			iis = ImageIO.createImageInputStream(fis);

			reader.setInput(iis, true);

			ImageReadParam param = reader.getDefaultReadParam();

			Rectangle rect = new Rectangle(x, y, width, height);

			// 提供一个 BufferedImage，将其用作解码像素数据的目标。
			param.setSourceRegion(rect);

			/*
			 * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将 它作为一个完整的
			 * BufferedImage 返回。
			 */
			BufferedImage bi = reader.read(0, param);
			// 保存新图片
			ImageIO.write(bi, "jpg", new File(target));
		} catch (Exception e) {
			// TODO: handle exception
		} finally{
			 try {
				 if (fis != null )   
	                 fis.close() ;          
	              if (iis != null )   
	                 iis.close();   
			} catch (Exception e2) {
				
			}
		}
	}

	/**
	 * 效果不如dengbiCompress
	 * @param originalFile
	 *            原图像
	 * @param resizeFile
	 *            压缩后图片
	 * @param width
	 *            图像宽
	 * @param format
	 *            图片格式 jpg、png、gif
	 */
	public static void resize(File originalFile, File resizeFile, int width,
			String format) throws IOException {
		if (StringUtil.isNotEmpty(format) && "gif".equalsIgnoreCase(format)) {
			resize(originalFile, resizeFile, width, 1);
			return;
		}
		FileInputStream fis = new FileInputStream(originalFile);

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		int readLength = -1;
		int bufferSize = 1024;

		byte bytes[] = new byte[bufferSize];
		while ((readLength = fis.read(bytes, 0, bufferSize)) != -1) {
			bos.write(bytes, 0, readLength);
		}

		byte[] in = bos.toByteArray();
		fis.close();
		bos.close();

		Image inputImage = Toolkit.getDefaultToolkit().createImage(in);
		waitForImage(inputImage);

		int imageWidth = inputImage.getWidth(null);
		if (imageWidth < 1)
			throw new IllegalArgumentException("image width " + imageWidth
					+ " is out of range");
		int imageHeight = inputImage.getHeight(null);
		if (imageHeight < 1)
			throw new IllegalArgumentException("image height " + imageHeight
					+ " is out of range");

		int height = -1;
		double scaleW = (double) imageWidth / (double) width;
		double scaleY = (double) imageHeight / (double) height;

		if (scaleW >= 0 && scaleY >= 0) {
			if (scaleW > scaleY) {
				height = -1;
			} else {
				width = -1;
			}
		}

		Image outputImage = inputImage.getScaledInstance(width, height,
				Image.SCALE_DEFAULT);
		checkImage(outputImage);
		encode(new FileOutputStream(resizeFile), outputImage, format);
	}

	/**
	 * 缩放gif图片
	 * 
	 * @param originalFile
	 * @param resizeFile
	 * @param width
	 * @param quality
	 *            缩放比例
	 * @throws IOException
	 */
	private static void resize(File originalFile, File resizeFile, int width,
			float quality) throws IOException {
		ImageIcon icon = new ImageIcon(originalFile.getCanonicalPath());

		Image img = icon.getImage();
		Image resizedImage = null;

		int iwidth = img.getWidth(null);
		int iheight = img.getHeight(null);
		if (iwidth > iheight) {
			resizedImage = img.getScaledInstance(width, (width * iheight)
					/ iwidth, Image.SCALE_SMOOTH);
		} else {
			resizedImage = img.getScaledInstance((width * iwidth) / iheight,
					width, Image.SCALE_SMOOTH);
		}

		Image temp = new ImageIcon(resizedImage).getImage();

		BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
				temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

		Graphics g = bufferedImage.createGraphics();
		g.setColor(Color.white);
		g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
		g.drawImage(temp, 0, 0, null);
		g.dispose();

		float softFactor = 0.05f;
		float[] softArray = { 0, softFactor, 0, softFactor,
				1 - (softFactor * 4), softFactor, 0, softFactor, 0 };

		Kernel kernel = new Kernel(3, 3, softArray);
		ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
		bufferedImage = cop.filter(bufferedImage, null);

		FileOutputStream fos = new FileOutputStream(resizeFile);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
		JPEGEncodeParam param = encoder
				.getDefaultJPEGEncodeParam(bufferedImage);
		param.setQuality(quality, true);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(bufferedImage);
	}

	private static void encode(OutputStream outputStream, Image outputImage,
			String format) throws IOException {
		int imageWidth = outputImage.getWidth(null);
		if (imageWidth < 1)
			throw new IllegalArgumentException("image width " + imageWidth
					+ " is out of range");
		int imageHeight = outputImage.getHeight(null);
		if (imageHeight < 1)
			throw new IllegalArgumentException("image height " + imageHeight
					+ " is out of range");

		BufferedImage bi = new BufferedImage(imageWidth, imageHeight,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = bi.createGraphics();
		g2.drawImage(outputImage, 0, 0, null);
		ImageIO.write(bi, format, outputStream);
		outputStream.flush();

	}

	private static void checkImage(Image outputImage) {
		waitForImage(outputImage);
		int imageWidth = outputImage.getWidth(null);
		if (imageWidth < 1)
			throw new IllegalArgumentException("image width " + imageWidth
					+ " is out of range");
		int imageHeight = outputImage.getHeight(null);
		if (imageHeight < 1)
			throw new IllegalArgumentException("image height " + imageHeight
					+ " is out of range");

	}

	private static void waitForImage(Image inputImage) {
		try {
			tracker.addImage(inputImage, 0);
			tracker.waitForID(0);
			tracker.removeImage(inputImage, 0);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
